/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#include "StdAfx.h"
#include "MIPLocator.h"

#include <Winsock2.h>

#include <algorithm>

//---------------------------------------------------------------------------

MIPLocator::MIPLocator(void)
{
	xDataLoaded = false;

	impIpToLocation = false;
	impGeoIP = false;
}

MIPLocator::~MIPLocator(void)
{
	CleanUp();
}

//---------------------------------------------------------------------------

void MIPLocator::CleanUp(void)
{
	theList.clear();
}

//---------------------------------------------------------------------------

void MIPLocator::InternalInit(void)
{
	CleanUp();
}

bool MIPLocator::InternalProcessLine(char *buf)
{
	if(impIpToLocation)
		return InternalProcessLineIpToLocation(buf);

	if(impGeoIP)
		return InternalProcessLineGeoIP(buf);

	return false;
}

bool MIPLocator::InternalProcessLineIpToLocation(char *buf)
{
	MIPRangeCountry rec;
	bool res;

	if(buf==NULL){
		// nothing to process
		return true;
	}

	int i, len;
	len = (int)strlen(buf);
	int pos1, pos2;

	i = pos1 = pos2 = 0;

	while(i<len && pos2==0){
		if(buf[i]==',')
			if(pos1==0) pos1 = i;
			else        pos2 = i;
		i++;
	}

	if(pos2==0) return false;

	buf[pos1] = buf[pos2] = 0;

	rec.xIpStart    = (DWORD)atof(&buf[0]);
	rec.xIpEnd      = (DWORD)atof(&buf[pos1+1]);
	rec.xCountry[0] = buf[pos2 + 2];
	rec.xCountry[1] = buf[pos2 + 3];
	rec.xCountry[2] = 0;

	res = true;
	try{
		theList.push_back(rec);
	}
	catch(...){
		res = false;
	}
	return res;
}

bool MIPLocator::InternalProcessLineGeoIP(char *buf)
{
	MIPRangeCountry rec;
	bool res;

	if(buf==NULL){
		// nothing to process
		return true;
	}

	int i, len;
	len = (int)strlen(buf);
	int pos1, pos2, pos3, pos4, pos5;

	i = pos1 = pos2 = pos3 = pos4 = pos5 = 0;

	while(i<len && pos5==0){
		if(buf[i]==',')
			if(pos1==0) pos1 = i;
			else
				if(pos2==0) pos2 = i;
				else
					if(pos3==0) pos3 = i;
					else        
						if(pos4==0) pos4 = i;
						else        pos5 = i;
		i++;
	}

	if(pos5==0) return false;

	buf[pos3 - 1] = buf[pos4 - 1] = 0;

	rec.xIpStart    = (DWORD)atof(&buf[pos2 + 2]);
	rec.xIpEnd      = (DWORD)atof(&buf[pos3 + 2]);
	rec.xCountry[0] = buf[pos4 + 2];
	rec.xCountry[1] = buf[pos4 + 3];
	rec.xCountry[2] = 0;

	res = true;
	try{
		theList.push_back(rec);
	}
	catch(...){
		res = false;
	}
	return res;
}

bool MIPLocator::InternalSave(void)
{
	return false;
}

//---------------------------------------------------------------------------

int MIPLocator::GetSize(void)
{
	return (int)theList.size();
}

//---------------------------------------------------------------------------

void MIPLocator::Sort(void)
{
	theList.sort();
}

CString MIPLocator::GetCountry(DWORD ipIn)
{
	/*
	MIPRangeCountry rec;

	rec.Initialize();
	rec.xIpStart = ntohl(ipIn);
	std::binary_search(theList.begin(), theList.end(), rec);
	return (rec.xCountry[0]!=0) ? rec.xCountry : NULL;
	*/

	MIPRangeCountry elem;
	bool found;
	CString str;
	DWORD ipa;

	ipa = ntohl(ipIn);

	found = false;
	for(iter=theList.begin(); iter!=theList.end() && !found; iter++){
		elem = *iter;
		if(ipa>=elem.xIpStart && ipa<=elem.xIpEnd){
			str = elem.xCountry;
			found = true;
		}
	}

	if(!found) str = _T("--");

	return str;
}

//---------------------------------------------------------------------------

bool MIPLocator::ImportIpToLocation(CString str)
{
	impIpToLocation = true;
	impGeoIP = false;
	CleanUp();
	return LoadFromFile(str);
}

bool MIPLocator::ImportGeoIP(CString str)
{
	impIpToLocation = false;
	impGeoIP = true;
	CleanUp();
	return LoadFromFile(str);
}

//---------------------------------------------------------------------------

bool MIPLocator::ExportAsBinary(CString fileNameIn)
{
	MIPRangeCountry elem;
	BYTE data[10];
	bool res;

	std::fstream fs;
	fs.open((char*)(LPCSTR)fileNameIn, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
	if(fs.fail())
		return false;

	res = true;

	for(iter=theList.begin(); iter!=theList.end() && res; iter++){
		elem = *iter;
		memcpy(&data[0], &elem.xIpStart, 4);
		memcpy(&data[4], &elem.xIpEnd, 4);
		data[8] = elem.xCountry[0];
		data[9] = elem.xCountry[1];

		try{
			fs.write((char*)data, 10);
		}
		catch(...){
			res = false;
		}
		
	}

	fs.close();

	return res;
}

//---------------------------------------------------------------------------

void MIPLocator::Clear(void)
{
	CleanUp();
}

//---------------------------------------------------------------------------
